package com.tanhua.dubbo.api;

import com.tanhua.domain.mongo.*;
import com.tanhua.domain.vo.PageResult;
import com.tanhua.dubbo.util.IdSequeue;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Service;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;

import java.util.ArrayList;
import java.util.List;

/**
 * @author anshuai
 * @create 2021-01-30 15:56
 */
@Slf4j
@Service
public class PublishApiImpl implements PublishApi {

    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private IdSequeue idSequeue;

    /**
     * 查询推荐的动态-给某用户推荐的好友动态
     *
     * @param page     页码
     * @param pagesize 查询几条
     * @param userId   用户id
     * @return
     */
    @Override
    public PageResult<Publish> findByRecommend(int page, int pagesize, long userId) {
        //创建条件查询用户的推荐动态
        Criteria criteria = Criteria.where("userId").is(userId).and("publishId").ne(null);
        Query query = new Query(criteria)
                .with(Sort.by(Sort.Order.desc("score")))
                .with(PageRequest.of(page - 1, pagesize));

        //根据条件查询推荐的动态id
        List<RecommendQuanZi> quanZiList = mongoTemplate.find(query, RecommendQuanZi.class);
        //查询推荐的动态总数
        long count = mongoTemplate.count(query, RecommendQuanZi.class);

        //创建存储动态数据的集合
        ArrayList<Publish> publishList = new ArrayList<>();
        //循环遍历quanZiList集合根据动态id查询动态数据
        for (RecommendQuanZi quanZi : quanZiList) {
            Publish publish = mongoTemplate.findById(quanZi.getPublishId(), Publish.class);
            publishList.add(publish);
        }

        //计算分了多少页
        int pages = (int) Math.ceil(count * 1.0 / pagesize);

        return new PageResult<>((int) count, pagesize, pages, page, publishList);
    }

    /**
     * 发布动态（保存动态）
     *
     * @param publish
     */
    @Override
    public String savePublish(Publish publish) {
        //1. 把publish数据保存到quanzi_publish表里
        publish.setId(ObjectId.get());
        publish.setPid(idSequeue.getNextId("quanzi_publish"));
        publish.setCreated(System.currentTimeMillis());
        //保存
        mongoTemplate.save(publish);

        log.info("保存动态数据：{}", publish);

        //2. 把动态记录保存到用户自己的相册表 quanzi_album_用户id
        Album album = new Album();
        album.setId(ObjectId.get());
        album.setPublishId(publish.getId());
        album.setCreated(System.currentTimeMillis());

        //每个用户都有一张自己的相册表,所以表名后面要加用户id加以区分
        mongoTemplate.save(album, "quanzi_album_" + publish.getUserId());
        log.info("记录到相册表{}，数据:{}", "quanzi_album_" + publish.getUserId(), album);

        //3. 把动态记录保存到所有好友的时间线表 quanzi_time_line_好友id
        Query query = new Query(Criteria.where("userId").is(publish.getUserId()));
        List<Friend> friendList = mongoTemplate.find(query, Friend.class);
        for (Friend friend : friendList) {
            TimeLine timeLine = new TimeLine();
            timeLine.setId(ObjectId.get());
            timeLine.setCreated(System.currentTimeMillis());
            timeLine.setPublishId(publish.getId());
            timeLine.setUserId(publish.getUserId());

            //将数据保存到时间线表中
            mongoTemplate.save(timeLine, "quanzi_time_line_" + friend.getFriendId());
            log.info("记录到时间线表{}，数据：{}", "quanzi_time_line_" + friend.getFriendId(), timeLine);
        }

        return publish.getId().toHexString();
    }

    /**
     * 分页查询某一用户的时间线动态（某一用户的好友动态列表）
     *
     * @param userId   用户id
     * @param page     页码
     * @param pagesize 查询几条
     * @return
     */
    @Override
    public PageResult<Publish> findTimelinePublishList(Long userId, int page, int pagesize) {
        //1.按照发布时间降序排列分页查询
        Query query = new Query()
                .with(Sort.by(Sort.Order.desc("created")))
                .with(PageRequest.of(page - 1, pagesize));
        //查询好友的时间线动态(包含动态数据的id)
        List<TimeLine> timeLineList = mongoTemplate.find(query, TimeLine.class, "quanzi_time_line_" + userId);
        //查询好友动态列表数量
        long count = mongoTemplate.count(query, TimeLine.class, "quanzi_time_line_" + userId);

        //创建集合存储好友动态数据
        List<Publish> publishList = new ArrayList<>();
        for (TimeLine timeLine : timeLineList) {
            Publish publish = mongoTemplate.findById(timeLine.getPublishId(), Publish.class);
            //将得到的动态数据添加到事先准备好的集合中
            publishList.add(publish);
        }

        //计算分了多少页
        int pages = (int) Math.ceil(count * 1.0 / pagesize);

        //返回数据
        return new PageResult<>((int) count, pagesize, pages, page, publishList);
    }

    /**
     * 查询相册-查询某一用户的相册（动态）
     *
     * @param page     页码
     * @param pagesize 查询几条
     * @param userId   用户id
     * @return
     */
    @Override
    public PageResult<Publish> findAlbumList(int page, int pagesize, long userId) {
        //查询当前用户自己的相册表动态数据
        Query query = new Query()
                .with(Sort.by(Sort.Order.desc("created")))
                .with(PageRequest.of(page - 1, pagesize));

        //因为每张用户的表明都不一样,所以要指定表名
        List<Album> albumList = mongoTemplate.find(query, Album.class, "quanzi_album_" + userId);
        //计算总数
        long count = mongoTemplate.count(query, Album.class, "quanzi_album_" + userId);

        //创建集合存储动态数据
        List<Publish> publishList = new ArrayList<>();
        for (Album album : albumList) {
            Publish publish = mongoTemplate.findById(album.getPublishId(), Publish.class);
            //将查到的自己的动态数据存放到准备好的动态集合中
            publishList.add(publish);
        }

        //计算总页数
        int pages = (int) Math.ceil(count * 1.0 / pagesize);

        //返回当前用户的动态数据的分页对象
        return new PageResult<>((int) count, pagesize, pages, page, publishList);
    }

    /**
     * 查询一条动态数据
     *
     * @param publishId 动态id
     * @return
     */
    @Override
    public Publish findById(String publishId) {
        return mongoTemplate.findById(new ObjectId(publishId), Publish.class);
    }

    /**
     * 分页查询某一用户发布的动态列表
     *
     * @param page     页码
     * @param pagesize 查询几条
     * @param uid      用户id
     * @param state    动态的审核状态
     * @return
     */
    @Override
    public PageResult<Publish> findPublishListByState(int page, int pagesize, Long uid, Integer state) {
        Query query = new Query()
                .with(Sort.by(Sort.Order.desc("created")))
                .with(PageRequest.of(page - 1, pagesize));

        if (uid != null) {
            //追加条件
            query.addCriteria(Criteria.where("userId").is(uid));
        }

        if (state != null) {
            query.addCriteria(Criteria.where("state").is(state));
        }

        List<Publish> publishList = mongoTemplate.find(query, Publish.class);
        long count = mongoTemplate.count(query, Publish.class);
        int pages = (int) Math.ceil(count * 1.0 / pagesize);

        return new PageResult<>((int) count, pagesize, pages, page, publishList);
    }

    /**
     * 更新审核状态
     * @param publish
     */
    @Override
    public void updateState(Publish publish) {
        Query query = new Query(Criteria.where("id").is(publish.getId()));
        Update update = new Update().set("state", publish.getState());
        mongoTemplate.findAndModify(query,update,Publish.class);
    }

    /**
     * 根据pid的集合，查询对应的动态集合
     * @param pidList pid集合
     * @return
     */
    @Override
    public List<Publish> findPublishByPids(List<Long> pidList) {
        Query query = new Query(Criteria.where("pid").in(pidList));

        return mongoTemplate.find(query,Publish.class);
    }
}
